<template>
    <section class="page-wrap">
        <!-- <a-spin :spinning="loading"> -->
        <div class="page-header">
            <div class="page-title">网盘存储
                <QuestionCircleOutlined class="ml-8" @click="openDocs('/docs/help_document/manual/storage/')" />
            </div>
            <div class="fz-12 col-8A93A7 mr-32">当前存储费用: <span class="col-money">{{ formatDiskStorageFee()
            }}</span>/小时=存储单价：<span class="col-money">{{
    form.netDiskStoragePrice }}</span>/小时*GB*已使用 <span class="col-money">{{
        printSize(form.totalSize) }}</span></div>

            <a-upload name="file" action="" :custom-request="uploadFile" :show-upload-list="false"  v-if="form.netDiskList?.length">
                <a-button type="primary">上传</a-button>
            </a-upload>

            <a-button type="primary" v-else @click="modalVisible = true">上传</a-button>
        </div>
        <div class="page-content">
            <a-tabs v-model:activeKey="activeKey" @change="changeTab" v-if="form.netDiskList?.length">
                <a-tab-pane v-for="(item, index) in form.netDiskList" :key="index" :tab="item.name">
                    <a-table :dataSource="tableList" :pagination="false" class="mb-16" :loading="tableLoading">
                        <a-table-column key="name" title="文件名" data-index="name">
                            <template #default="{ record }">
                                {{ (record.name).replace((config.basePath).substring(1) + '/', "") }}
                            </template>
                        </a-table-column>
                        <a-table-column key="size" title="大小" data-index="size">
                            <template #default="{ record }">
                                {{ printSize(record.size) }}
                            </template>
                        </a-table-column>
                        <a-table-column key="lastModified" title="更新时间" data-index="lastModified">
                            <template #default="{ record }">
                                {{ dayjs(record.lastModified).format("YY-MM-DD HH:mm:ss") }}
                            </template>
                        </a-table-column>
                        <a-table-column key="action" title="操作">
                            <template #default="{ record }">
                                <a-popconfirm title="确定要删除网盘存储吗?" @confirm="deleteStorage(record.name)">
                                    <a-button type="link" style="padding-left:0;">删除</a-button>
                                </a-popconfirm>
                            </template>
                        </a-table-column>
                    </a-table>

                    <a-button @click="prevPage" type="primary" v-if="currentPn > 0" class="mb-16 mr-8">上一页</a-button>

                    <a-button @click="nextPage" type="primary" class="mb-16">下一页</a-button>
                </a-tab-pane>
            </a-tabs>

            <div v-else>
                <a-table :dataSource="tableList"></a-table>
            </div>
        </div>

        <GpuDrawer v-model="docVisible" v-if="docVisible" :url="docurl"></GpuDrawer>

        <a-modal v-model:visible="open" title="文件上传" :keyboard="false" :mask-closable="false" :closable="false" centered>
            <template #footer>
                <a-button key="recharge" @click="handelCancel">取消上传</a-button>
                <a-button key="create" type="primary" @click="handelOk" v-if="uploadProgress == 100">完成</a-button>
            </template>
            <div class="col-level2 fz-14">文件上传中，请勿取消，否则上传失败。</div>
            <a-progress :percent="uploadProgress" />
        </a-modal>

        <!-- 引导百度网盘上传 -->
        <a-modal v-model:visible="modalVisible" title="网盘上传" @ok="openDocs('/docs/help_document/practice/baidupcs')" ok-text="查看文档" :confirm-loading="confirmLoading">
            <div class="instance-modal">
                <div class="fz-14 col-level2">推荐您使用百度网盘上传数据</div>
            </div>
        </a-modal>
    </section>
</template>

<script setup name="GpuImage">
import { reactive, ref } from 'vue'
import {
    QuestionCircleOutlined,
} from '@ant-design/icons-vue';
import { XsyMessage } from 'libs/util.toast'
import { getStoragepPage, getNetdiskTokenApi } from 'api/modules/api.storage'
import { Minio, initMinio, putObject } from 'minio-js'
import { printSize } from '@/libs/util.common'
import dayjs from "dayjs"
import axios from "axios";

const modalVisible = ref(false)

const tableList = ref([]);
const queryParams = ref({
    pn: 1,
    ps: 10
})

const activeKey = ref(0);
const form = ref({
    netDiskList: []
})

const docVisible = ref(false)
const docurl = ref('')
const openDocs = (key)=> {
    modalVisible.value = false
    docVisible.value = true
    docurl.value = window.location.origin + key
}
// 获取tablist
const getList = (key) => {
    const params = {
        ...queryParams.value,
    }
    getStoragepPage(params).then(res => {
        form.value = res.data
        if (!res.data?.netDiskList?.length) {
            return
        }
        getNetdiskToken(res.data?.netDiskList[key]?.dcId)
    })
}

getList(activeKey.value)

// 上一页
const resetData = () => {
    currentPn.value = 0
    totalDataList.value = []
}
const currentPn = ref(0)  // 当前页码
const prevPage = () => {
    if (currentPn.value <= 0) {
        return
    }
    currentPn.value = currentPn.value - 1
    tableList.value = totalDataList.value.slice(currentPn.value * 10, currentPn.value * 10 + 10)
}

// 下一页
const nextPage = () => {
    currentPn.value = 1 + currentPn.value
    if (currentPn.value * 10 < totalDataList.value.length) {
        tableList.value = totalDataList.value.slice(currentPn.value * 10, currentPn.value * 10 + 10)
    } else {
        if (tableList.value.length < 10 || resultData.isTruncated == true) {
            currentPn.value = currentPn.value - 1
            return
        } else {
            getStorageList(resultData.value.nextContinuationToken)
        }
    }

}

// 切换tab,刷新存储列表
const changeTab = (key) => {
    getNetdiskToken(form.value?.netDiskList[key]?.dcId)
}

// 获取token配置
const config = ref({})
const getNetdiskToken = (dcId) => {
    if (!dcId) {
        return
    }
    getNetdiskTokenApi({ dcId }).then(res => {
        if (res.code == 0) {
            config.value = res.data
            getStorageList()
        }
    }).catch((err) => {

    })
}

// 获取 HOST
const getHost = (myStr) => {
    const reg2 = /:\/\/(.[^/:]+)/;
    var myResult = myStr.match(reg2);
    return myResult[1]
}

// 上传操作
const uploadProgress = ref(0)

// 获取网盘列表
const totalDataList = ref([])  // 前端用来做分页的总数据源

const tableLoading = ref(true)
const resultData = ref({})
const getStorageList = (nextContinuationToken = '') => {
    const minioClient = new Minio.Client({
        endPoint: getHost(config.value.endpoint),
        useSSL: false,
        accessKey: config.value.accessKey,
        secretKey: config.value.secretKey,
        sessionToken: config.value.sessionToken
    })

    tableList.value = []

    var stream = minioClient.listObjectsV2Query(config.value.bucket, config.value.basePath, nextContinuationToken, '', 10, '')
    stream.on('data', function (res) {
        tableLoading.value = false
        resultData.value = res
        // 只有一条数据的时候判断一下是否为basePath,空目录不展示
        if (res.objects?.length == 1 && res.objects?.[0]?.name?.indexOf('/') == res.objects?.[0]?.name?.length - 1) {
            tableList.value = []
        } else {
            tableList.value = res.objects
            // 最新请求的数据push到数组当中
            totalDataList.value = [...totalDataList.value, ...res.objects]

        }
    })
    stream.on('end', function () {
        tableLoading.value = false
    })
    stream.on('error', function () {
        tableLoading.value = false
    })

}

// 删除网盘存储
const deleteStorage = (name) => {
    const minioClient = new Minio.Client({
        endPoint: getHost(config.value.endpoint),
        useSSL: false,
        accessKey: config.value.accessKey,
        secretKey: config.value.secretKey,
        sessionToken: config.value.sessionToken
    })

    minioClient.removeObject(config.value.bucket, name, function (e) {
        XsyMessage.success('删除成功');
        // 删除重置本地存储数据
        resetData()
        getStorageList()
    })
}

//  GB内存计算
const printGBSize = val => {
    const GB = 1024 * 1024 * 1024
    if (!val) {
        return 0
    }

    return `${(val / GB).toFixed(2)}`
}

const formatDiskStorageFee = () => {
    let fee = ''
    fee = (form?.value?.netDiskStoragePrice * printGBSize(form?.value?.totalSize))
    if (parseFloat(fee) > 0 && parseFloat(fee) < 0.01) {
        fee = 0.01
    }

    return fee.toFixed(2)
}

const minioUploads = (file, progress, success, error) => {
    if (file.name.lastIndexOf('.') < 0) {
        error({ code: 500, msg: '文件格式错误,请重新上传' })
        return false
    }

    /*
    获取文件类型以及文件路径
    * */
    const suffixType = file && file.name ? file.name : ''
    const UrlName = `${config.value.basePath}/${suffixType}`

    /*
    * 获取服务器以及上传文件
    * */

    const minioClient = new Minio.Client({
        endPoint: getHost(config.value.endpoint),
        useSSL: false,
        accessKey: config.value.accessKey,
        secretKey: config.value.secretKey,
        sessionToken: config.value.sessionToken
    })

    minioClient.presignedPutObject(config.value.bucket, UrlName, 0.5 * 60 * 60, function (err, presignedUrl) {
        if (err) {
            error({ code: 500, msg: '未获取到文件服务器,请联系管理员' })
            return false
        }

        axios.put(presignedUrl, file, {
            headers: { 'Content-Type': file.type },
            timeout: 1000 * 60 * 30,
            onUploadProgress: function (progressEvent) {
                /*
                * 返回文件当前上传的进度
                * */
                progress({ loaded: progressEvent.loaded, total: progressEvent.total, proNum: Number((progressEvent.loaded / progressEvent.total * 100).toFixed(0)) })
            },
            cancelToken: Cancel.token
        }).then((res) => {
            if (res.status !== 200) {
                error({ code: 500, msg: '文件上传失败,请联系管理员' })
                return false
            }

            /*
            * 自定义上传成功后返回的信息
            * */
            success({
                data: {
                    url: `${getHost(config.value.endpoint)}/${config.value.bucket}/${UrlName}`,
                    name: file.name,
                    size: file.size,
                },
                code: 0,
                msg: '上传成功',
            })
        }).catch(() => {
            error({ data: null, code: 500, msg: '上传异常,请联系管理员', })
        })
    })
}

const open = ref(false)
function uploadFile(item) {
    const fileObj = item.file;
    open.value = true
    minioUploads(fileObj, progress => {
        //taskProgress data中定义的字段
        //上传中进度返回
        uploadProgress.value = progress.proNum
    }, res => {
        resetData()
        getStorageList()
        //成功时返回的信息
    }, error => {
        open.value = false
        XsyMessage.error('上传失败');
        //错误时返回呢信息
    })
}

let Cancel = axios.CancelToken.source()
const handelOk = () => {
    open.value = false
    uploadProgress.value = 0
}

// 取消上传
const handelCancel = () => {
    Cancel.cancel();
    Cancel = axios.CancelToken.source(); // 重新定义cancelToken
    open.value = false
    uploadProgress.value = 0
}

</script>

<style scoped lang="less">
.page-wrap {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.page-header {
    display: flex;
    align-items: center;
    height: 64px;
    background: #ffffff;
    margin-bottom: 4px;
    padding: 0 24px;

    .page-title {
        color: #223354;
        font-family: PingFang SC;
        font-size: 18px;
        font-style: normal;
        font-weight: 600;
        line-height: normal;
        padding-right: 8px;
        margin-right: 8px;
    }

    .page-title::after {
        display: block;
        content: '';
        height: 5px;
        background: linear-gradient(90deg, #07F 5.32%, rgba(255, 255, 255, 0.00) 103.53%);
    }
}

.page-content {
    flex: 1;
    background: #ffffff;
    padding: 24px;
    overflow-y: scroll;
}

.page-footer {
    background: #fff;
}

::v-deep(.page-content .ant-table-thead>tr>th) {
    color: #8A93A7;
    font-size: 14px;
    background: #F3F5F7;
    border: none;

    &::before {
        display: none;
    }
}
</style>
